package cate.game.role.pvp.eliterace;

import cate.common.table.d.GDEliteRace;
import cate.game.framework.advanced.AdvancedByteAttributes;
import cate.game.pvp.eliterace.data.EliteRaceKV;
import cate.game.pvp.eliterace.data.EliteRaceSpec;
import cate.game.pvp.eliterace.handler.EliteRaceHandler;
import cate.game.role.FuncOpenChecker;
import cate.game.role.Role;
import cate.game.role.fight.FuncPosition;
import cate.game.role.fight.Position;
import cate.game.role.pvp.eliterace.msg.EliteRaceInvitationResp;
import cate.game.role.pvp.eliterace.msg.EliteRaceLiteDataResp;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import easy.java.dev.note.NoteClass;
import easy.java.dev.note.NoteField;
import org.springframework.data.annotation.Transient;

import java.util.Objects;

import static cate.common.table.d.GDEliteRace.ATTRIBUTES_NOTICE_MASK;
import static cate.common.table.d.GDEliteRace.WHOLE_SEASON_TIME;
import static cate.common.table.d.GDFunc.ADVENTURE;
import static cate.common.table.d.GDFunc.ELITE_RACE;
import static cate.game.client.msg.MsgSender.send;

@NoteClass(value = "精英赛数据")
public class EliteRace extends FuncOpenChecker {

    @NoteField(value = "历史最高排名")
    public int topRank = -1;

    @NoteField(value = "积分赛排名")
    public int prRank = 0;

    @NoteField(value = "当前赛季")
    public int season;

    @NoteField(value = "当前赛季开启时间")
    public long seasonStartTime;

    @NoteField(value = "下个赛季开启的时间")
    public long nextSeasonStartTime;

    @NoteField(value = "分数")
    public long points;

    @Transient
    @NoteField(value = "当前赛季持续时间")
    @SuppressWarnings("unused")
    public transient long wholeSeasonTime = WHOLE_SEASON_TIME;

    @JsonProperty("seasonStartTime")
    @SuppressWarnings("unused")
    public long getSeasonStartTime() {
        return role.getGame().pvp.eliteRace.getHandler().getSeasonStartTime();
    }

    @JsonIgnore
    public EliteRaceBetPO betPO;

    public EliteRaceRedPacketPO redPacketPO;

    @JsonIgnore
    private byte attributeFlag;

    @JsonIgnore
    @Transient
    private transient final AdvancedByteAttributes attributes = AdvancedByteAttributes.of(attributeFlag);

    @Override
    public void initialize(Role role) {
        super.initialize(role);

        if (Objects.isNull(betPO)) {
            betPO = new EliteRaceBetPO();
        }

        betPO.initialize(role);

        if (Objects.isNull(redPacketPO)) {
            redPacketPO = new EliteRaceRedPacketPO();
        }

        redPacketPO.initialize(role);
    }

    @Override
    public void onEnter() {
        super.onEnter();
        betPO.onEnter();
        redPacketPO.onEnter();
        checkSeason();
    }

    @JsonProperty("betTimes")
    public int getBetTimes() {
        return betPO.rdMap.size();
    }

    @JsonProperty("coins")
    public int getCoins() {
        EliteRaceKV kv = role.getGame().pvp.eliteRace.getDataManager().getData();
        if (kv != null) {
            EliteRaceSpec spec = kv.getSpec();
            if (spec == null || spec.getStep() != 1 || betPO.hasBet(spec) == 1) {
                return 0;
            }
            return role.getGame().pvp.eliteRace.getHandler().hasRecvdRedPacket(role.getUid(), spec) ? GDEliteRace.FIXED_BET_NUM : 0;
        }
        return 0;
    }

    private void checkSeason() {
        int serverSeason = role.getGame().pvp.eliteRace.getHandler().getSeason();
        if (season != serverSeason) {
            this.season = serverSeason;
            this.attributes.clear();
            this.points = 0;
            betPO.onSeasonSwitch();
            redPacketPO.onSeasonSwitch();
        }
        this.nextSeasonStartTime = role.getGame().pvp.eliteRace.getHandler().getNextSeasonStartTime();
        this.seasonStartTime = role.getGame().pvp.eliteRace.getHandler().getSeasonStartTime();
    }

    @Override
    public int getFuncId() {
        return ELITE_RACE;
    }

    @Override
    public void onAfterOpen() {
        checkPosition();
    }

    public void checkPosition() {
        if (!open) {
            return;
        }
        if (role.getFight().funcPositions.get(ELITE_RACE) == null
                || role.getFight().funcPositions.get(ELITE_RACE).positions.isEmpty()) {
            Position position = role.getFight().getPosition(ADVENTURE);
            if (position != null) {
                FuncPosition funcPosition = new FuncPosition();
                funcPosition.init();
                funcPosition.funcId = ELITE_RACE;
                funcPosition.positions.add(position.copy());
                role.getGame().fight.position.updatePosition(role, funcPosition);
            }
        }
    }

    public void liteNotice() {
        EliteRaceHandler handler = role.getGame().pvp.eliteRace.getHandler();
        int serverSeason = handler.getSeason();
        EliteRaceKV kv = role.getGame().pvp.eliteRace.getDataManager().getData();
        send(role::sendNow, new EliteRaceLiteDataResp(
                kv.getSpec(),
                handler.getSeasonStartTime(),
                handler.getNextSeasonStartTime(),
                getNotice(),
                betPO.hasBet(kv.getSpec()),
                redPacketPO.hasRedPacket(kv.getSpec())
        ));
    }

    private byte getNotice() {
        byte notice = 0;
        EliteRaceKV kv = role.getGame().pvp.eliteRace.getDataManager().getData();
        if (Objects.isNull(kv.getSpec()) || kv.getSpec().getPeriod() < 1) {
            if (!attributes.hasAttribute(ATTRIBUTES_NOTICE_MASK)) {
                notice = 1;
                attributes.setAttribute(ATTRIBUTES_NOTICE_MASK);
            }
        }
        return notice;
    }

    public void handleInvitation(int prRank) {
        send(role::sendNow, new EliteRaceInvitationResp(prRank));
    }

    public void refreshRecord(int rank) {
        if (topRank < 0 || rank < topRank) {
            topRank = rank;
        }
        role.getHistory().action.eliteRaceJoin();
        role.getHistory().action.eliteRaceRankTimes(rank);
    }
}
